package org.jg.arkanoid.util;

import java.util.ArrayList;
import java.util.Collection;

import org.jg.arkanoid.gameobjects.GameObject;

public class JGUtil 
{
	public static double pointDistance(Vector v1, Vector v2){
		return Math.hypot(v2.getX() - v1.getX(), v2.getY() - v1.getY());
	}
	
	public static Collection<Vector> getCrossPoints( Segment segment, Segment[] segments, boolean inBothSegments )
	{
		Collection<Vector> crossPoints = new ArrayList<Vector>();
		
		for(Segment seg : segments)
		{
			Vector crossPoint = getCrossPoint(segment, seg, inBothSegments);
			if(crossPoint != null)
			{
				crossPoints.add(crossPoint);
			}
		}
		
		return crossPoints;
	}
	
	public static Vector getClosestPoint( Vector anchorPoint, Collection<Vector> pointSet )
	{
		Vector closestPoint = JGUtil.getFirst(pointSet);
		double shortestDistance =  pointDistance(anchorPoint, closestPoint);
		
		for(Vector point : pointSet)
		{
			double currentDistance = pointDistance(anchorPoint, point);
			if(currentDistance < shortestDistance)
			{
				closestPoint = point;
				shortestDistance = currentDistance;
			}
		}
		
		return closestPoint;
	}
	
	public static Vector getCrossPoint( Segment segment1, Segment segment2, boolean inBothSegments )
	{
		Vector crossPoint = null;
		
		double x1 = segment1.getX1();
		double x2 = segment1.getX2();
		double x3 = segment2.getX1();
		double x4 = segment2.getX2();
		
		double y1 = segment1.getY1();
		double y2 = segment1.getY2();
		double y3 = segment2.getY1();
		double y4 = segment2.getY2();
		
		double u_denominator = (y4 - y3)*(x2 - x1) - (x4 - x3)*(y2 - y1);
		
		if(u_denominator == 0) //Lines parallel
		{
			return crossPoint;
		}
		
		double u_a = ( (x4 - x3)*(y1 - y3) - (y4 - y3)*(x1 - x3) )/u_denominator;
		double u_b = ( (x2 - x1)*(y1 - y3) - (y2 - y1)*(x1 - x3) )/u_denominator;
		
		if( inBothSegments )
		{
			if( u_a >= 0 && u_a <= 1 && u_b >= 0 && u_b <= 1 ) //Crosspoint is inside of both segments
			{
				double xCross = x1 + u_a*(x2 - x1);
				double yCross = y1 + u_a*(y2 - y1);
				crossPoint = new Vector(xCross, yCross);
			}
		}
		else
		{
			if( u_a >= 0 && u_a <= 1 ) //Crosspoint is inside first segment
			{
				double xCross = x1 + u_a*(x2 - x1);
				double yCross = y1 + u_a*(y2 - y1);
				crossPoint = new Vector(xCross, yCross);
			}
			else if( u_b >= 0 && u_b <= 1 )
			{
				double xCross = x3 + u_b*(x4 - x3);
				double yCross = y3 + u_b*(y4 - y3);
				crossPoint = new Vector(xCross, yCross);
			}
		}
		
		return crossPoint;
	}
	
	public static boolean rectangleObjectContainsPoint( GameObject obj, Vector point )
	{
		double x1 = obj.getPosition().getX();
		double y1 = obj.getPosition().getY();
		double x2 = x1 + obj.getWidth();
		double y2 = y1 + obj.getHeight();
		
		double pX = point.getX();
		double pY = point.getY();
		
		return pX>=x1 && pX<=x2 && pY>=y1 && pY<=y2;
	}
	
	public static Segment[] getObjectSegments(GameObject gameObject)
	{
		if(gameObject == null)
		{
			return new Segment[0];
		}
		
		Segment[] segments = new Segment[4];
		
		Vector position = gameObject.getPosition();
		int width = gameObject.getWidth();
		int height = gameObject.getHeight();
		
		segments[0] = new Segment(position.getX(), position.getY(), position.getX() + width, position.getY());
		segments[1] = new Segment(position.getX() + width, position.getY(), position.getX() + width, position.getY() + height);
		
		segments[2] = new Segment(position.getX(), position.getY() + height, position.getX() + width, position.getY() + height);
		segments[3] = new Segment(position.getX(), position.getY(), position.getX(), position.getY() + height);
		
		return segments;
	}
	
	public static <T> T getFirst( Collection<T> collection)
	{
		T firstElement = null;
		if( collection != null )
		{
			for(T element : collection)
			{
				firstElement = element;
				break;
			}
		}
		return firstElement;
	}
}
